/*
 * dmuploader.js - Jquery File Uploader - 0.1
 * http://www.daniel.com.uy/projects/jquery-file-uploader/
 * 
 * Copyright (c) 2013 Daniel Morales
 * Dual licensed under the MIT and GPL licenses.
 * http://www.daniel.com.uy/doc/license/
 */

(function ($) {
    var pluginName = 'dmUploader';

    // These are the plugin defaults values
    var defaults = {
        url: document.URL,
        formElemId: "",
        method: 'POST',
        extraData: {},
        maxFileSize: 0,
        allowedTypes: '*',
        extFilter: null,
        dataType: null,
        fileName: 'file',
        onInit: function () {
        },
        onFallbackMode: function () {
        },
        onNewFile: function (id, file) {
        },
        onBeforeUpload: function (id) {
        },
        onComplete: function () {
        },
        onUploadProgress: function (id, percent) {
        },
        onUploadSuccess: function (id, data) {
        },
        onUploadError: function (id, message) {
        },
        onFileTypeError: function (file) {
        },
        onFileSizeError: function (file) {
        },
        onFileExtError: function (file) {
        },
        onSubmit: function(){

        },
        onSubmited:function(){

        }
    };

    var QUEUE_FILE_TYPE_INPUT_FORM = 0;
    var QUEUE_FILE_TYPE_DRAG_FILE = 1;

    var QueueFile = function(file, type){
        this.file = file;
        this.type = type;
    };

    var DmUploader = function (element, options) {
        this.element = $(element);

        this.settings = $.extend({}, defaults, options);

        if (!this.checkBrowser()) {
            return false;
        }

        this.init();

        return true;
    };

    DmUploader.prototype.checkBrowser = function () {
        /*if(window.FormData === undefined){
         this.settings.onFallbackMode.call(this.element, 'Browser doesn\'t support From API');

         return false;
         }*/

        if (this.element.find('input[type=file]').length > 0) {
            return true;
        }

        /* if (!this.checkEvent('drop', this.element) || !this.checkEvent('dragstart', this.element)){
         this.settings.onFallbackMode.call(this.element, 'Browser doesn\'t support Ajax Drag and Drop');

         return false;
         }*/

        return true;
    };

    DmUploader.prototype.checkEvent = function (eventName, element) {
        var element = element || document.createElement('div');
        var eventName = 'on' + eventName;

        var isSupported = eventName in element;

        if (!isSupported) {
            if (!element.setAttribute) {
                element = document.createElement('div');
            }
            if (element.setAttribute && element.removeAttribute) {
                element.setAttribute(eventName, '');
                isSupported = typeof element[eventName] == 'function';

                if (typeof element[eventName] != 'undefined') {
                    element[eventName] = undefined;
                }
                element.removeAttribute(eventName);
            }
        }

        element = null;
        return isSupported;
    };

    DmUploader.prototype.init = function () {
        var widget = this;

        widget.queue = [];
        widget.queuePos = -1;
        widget.queueRunning = false;

        // -- Drag and drop event
        widget.element.on('drop', function (evt) {
            evt.preventDefault();
            var files = evt.originalEvent.dataTransfer.files;
            if(files){
                widget.queueFiles(files, QUEUE_FILE_TYPE_DRAG_FILE);
            }
        });

        //-- Optional File input to make a clickable area
        widget.element.find('input[type=file]').on('change', function (evt) {
            if(!evt.target.value)  {
                return;
            }
            widget.queueFiles(evt.target, QUEUE_FILE_TYPE_INPUT_FORM);
            $(this).val('');
        });

        this.settings.onInit.call(this.element);
    };

    DmUploader.prototype.queueFiles = function (files, type) {
        var j = this.queue.length;
        if(type === QUEUE_FILE_TYPE_INPUT_FORM){
            // Check file extension
            if (this.settings.extFilter != null) {
                var extList = this.settings.extFilter.toLowerCase().split(';');

                var ext = files.value.toLowerCase().split('.').pop();

                if ($.inArray(ext, extList) < 0) {
                    this.settings.onFileExtError.call(this.element, files);
                    return;
                }
            }
            if(files.files){
                var fileSize = files.files[0].size;
                // Check file size
                if ((this.settings.maxFileSize > 0) &&
                    (fileSize > this.settings.maxFileSize)) {
                    this.settings.onFileSizeError.call(this.element, files);
                    return;
                }
            }
            this.queue.push(new QueueFile(files, QUEUE_FILE_TYPE_INPUT_FORM));
            var index = this.queue.length - 1;
            this.settings.onNewFile.call(this.element, index, files);
        }
        else{
            for (var i = 0; i < files.length; i++) {
                var file = files[i];

                // Check file size
                if ((this.settings.maxFileSize > 0) &&
                    (file.size > this.settings.maxFileSize)) {

                    this.settings.onFileSizeError.call(this.element, file);

                    continue;
                }

                // Check file type
                if ((this.settings.allowedTypes != '*') && !file.type.match(this.settings.allowedTypes)) {

                    this.settings.onFileTypeError.call(this.element, file);

                    continue;
                }

                // Check file extension
                if (this.settings.extFilter != null) {
                    var extList = this.settings.extFilter.toLowerCase().split(';');

                    var ext = file.name.toLowerCase().split('.').pop();

                    if ($.inArray(ext, extList) < 0) {
                        this.settings.onFileExtError.call(this.element, file);

                        continue;
                    }
                }

                this.queue.push(new QueueFile(file,QUEUE_FILE_TYPE_DRAG_FILE));

                var index = this.queue.length - 1;

                this.settings.onNewFile.call(this.element, index, file);
            }
        }


        // Only start Queue if we haven't!
        if (this.queueRunning) {
            return false;
        }

        // and only if new Failes were succefully added
        if (this.queue.length == j) {
            return false;
        }

        this.processQueue();

        return true;
    };

    DmUploader.prototype.processQueue = function () {
        var widget = this;

        widget.queuePos++;

        if (widget.queuePos >= widget.queue.length) {
            // Cleanup

            widget.settings.onComplete.call(widget.element);

            // Wait until new files are droped
            widget.queuePos = (widget.queue.length - 1);

            widget.queueRunning = false;

            return;
        }
        var queueFile = widget.queue[widget.queuePos];
        var file = queueFile.file;
       /* // Form Data
        var fd = new FormData();
        fd.append(widget.settings.fileName, file);

        // Append extra Form Data
        $.each(widget.settings.extraData, function (exKey, exVal) {
            fd.append(exKey, exVal);
        });*/

        widget.settings.onBeforeUpload.call(widget.element, widget.queuePos);

        widget.queueRunning = true;
        if (queueFile.type === QUEUE_FILE_TYPE_INPUT_FORM) {
            var options = {
                dataType: widget.settings.dataType,
                beforeSend: function () {
                },
                uploadProgress: function (event, position, total, percentComplete) {
                    widget.settings.onUploadProgress.call(widget.element, widget.queuePos, percentComplete);
                },
                success: function (data) {
                    widget.settings.onUploadSuccess.call(widget.element, widget.queuePos, data);
                    widget.processQueue();
                },
                complete: function (response) {

                },
                error: function (jqXHR, textStatus, errorThrown) {
                    widget.settings.onUploadError.call(widget.element, widget.queuePos, jqXHR.responseText);
                    widget.processQueue();
                }
            };

            $("#" + widget.settings.formElemId).ajaxSubmit(options);
            widget.settings.onSubmit.call();
            return;
        }


        var fileName = file.name;
        // Ajax Submit
        $.ajax({
            url: widget.settings.url,
            type: widget.settings.method,
            //dataType: widget.settings.dataType,
            data: file, //fd,
            cache: false,
            contentType: "application/octet-stream",
            processData: false,
            forceSync: false,
            headers: {"FILENAME": encodeURIComponent(fileName) },
            xhr: function () {
                var xhrobj = $.ajaxSettings.xhr();
                if (xhrobj.upload) {
                    xhrobj.upload.addEventListener('progress', function (event) {
                        var percent = 0;
                        var position = event.loaded || event.position;
                        var total = event.total || e.totalSize;
                        if (event.lengthComputable) {
                            percent = Math.ceil(position / total * 100);
                        }

                        widget.settings.onUploadProgress.call(widget.element, widget.queuePos, percent);
                    }, false);
                }

                return xhrobj;
            },
            success: function (data, message, xhr) {
                widget.settings.onUploadSuccess.call(widget.element, widget.queuePos, data);
            },
            error: function (xhr, status, errMsg) {
                widget.settings.onUploadError.call(widget.element, widget.queuePos, errMsg);
            },
            complete: function (xhr, textStatus) {
                widget.processQueue();
            }
        });
        widget.settings.onSubmited.call();
    };

    $.fn.dmUploader = function (options) {
        return this.each(function () {
            if (!$.data(this, pluginName)) {
                $.data(this, pluginName, new DmUploader(this, options));
            }
        });
    };

    // -- Disable Document D&D events to prevent opening the file on browser when we drop them
    $(document).on('dragenter', function (e) {
        e.stopPropagation();
        e.preventDefault();
    });
    $(document).on('dragover', function (e) {
        e.stopPropagation();
        e.preventDefault();
    });
    $(document).on('drop', function (e) {
        e.stopPropagation();
        e.preventDefault();
    });
})(jQuery);
